-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
solidified solid-three
#15
base: main
Are you sure you want to change the base?
Conversation
Implementation of proxy-based threejs renderer, based on the exploration done in the zustand-to-store branch: see #12 This branch deviates from the previous goal of staying close to r3f's codebase in favor of simplification and 'solidification'. How the props are managed (= applying jsx-props to three-instand and managing of the scene graph) and the Primitive-component are copied from the zustand-to-store branch. differences: - Custom event handling - Augment the threejs instance with far less in comparison then r3f: we only store the props of the component
Are these similarities and differences comparing this branch with I really don't have a clue how to assess the merits of this PR, sorry. We don't have a test suite, so I can't really do it empirically. There's not enough information in the PR to really understand the changes and any tradeoffs they imply. We really need user documentation, or at least LOTS of sample code. I think we're still in the unfortunate situation that someone can't really predict how to use the library without understanding both its implementation AND the tooling transformation it requires. Also, if you're still using "T.whatever", we don't need any custom tooling, and I'd prefer to keep it that way. Just give me sample code for the registrations. BTW you should change the version number from "0.2.0" to anything else. |
Prior - our event system was not bubbling events down the scene graph. - `event.stopPropagation()` prevented events from reaching objects behind the `Object3D` that called this event. After - adds event bubbling - adapts event.stopPropagation to stop event bubbling, similar to the DOM/react-three-fiber. - adds pointer and setPointer to ThreeContext The event propagation deviates from react-three-fiber regarding derived events: `on{Pointer|Mouse}Enter` and `on{Point|Mouse}Leave` are derived from `window.on{Pointer|Mouse}Move`. In react-three-fiber stopping propagation on a move-event has an impact on leave/enter-events: all the objects that are currently 'hovered' are 'unhovered' and their leave-eventhandlers are called. This includes the object that called event.stopPropagation(). See https://docs.pmnd.rs/react-three-fiber/api/events#event-propagation-(bubbling) for documentation. This is not an intuitive approach in my opinion. In the current implementation move events and derived events are separated from each other, stopping propagation move does not impact the object's hovered state, nor does it call the leave-eventhandler. Stopping propagation inside a move or derived eventhandler stops only the bubbling down of the specific eventhandler.
This commit ports react-three-fiber's tests to solid-three and adds testing utilities and components to a new entry: `@solid-three/testing`. The r3f tests are ported from `jest` and `testing-library/react` to `vitest` and `@solid-js/testing-library`. These tests are located at `./tests`. r3f has a package `react-three-fiber/test-renderer`. I took their WebGL2RenderingContext- and canvas-mock implementation and moved it to `src/testing`. Exports of `solid-three/testing`: - test() - A utility function to setup a testing environment. - Accepts as arguments - Accessor<ThreeComponent> - CanvasProps - Returns TestAPI = ThreeContext augmented with the eventRegistry-object and utility functions to assist with testing: unmount() and waitTillNextFrame(). - <TestCanvas/> - a mock of <Canvas/> to be used in non-DOM environments. Currently we have 1 standing bug. Most of the missing API has been re-implemented (see Fixes and Features). Missing API: - PointerCapture - onPointerMissed-event - Canvas-prop performance Bug: - Order of ThreeElement's children is not synchronised with the order of ThreeComponent's children-prop - see "can swap 4 array primitives" Fixes: - Update sub-properties when a property changes: - p.ex in <T.Mesh position={} position-x={}/> If props.position updates, position-x will be applied to it immediately after. - see "invalidates pierced props when root is changed" Features: - <Portal element={Object3D}/> = Portal accepts now an Object3D as optional element-prop. If it is defined it will render into that element instead of the scene. - Portal overwrite the ThreeContext's scene with props.element if it exists. - Config threeContext's gl, camera, scene and raycaster with props on <Canvas/> - Canvas' gl-prop accepts a callback: (canvas: HTMLCanvasElement) => THREE.WebGLRenderer. - Attach-prop accepts a callback, besides "string" - see "attaches Object3D children that use attachFns" - Extensible typing for T with namespace SolidThree. - extend() now only accepts SolidThree.Elements. - Allow Accessor<string[]> in useLoader: - p.ex useLoader(GLFLoader, () => ["string", "string"]) Returns Resource<readonly [GTLF, GLTF]> - see "can handle useLoader hook with an array of strings" - Cache results of useLoader - Optional setup-function in useLoader - see "can handle useLoader with a loader extension" - Add onUpdate-event: gets called on every prop-update. - see "onUpdate shouldn't update itself" - Initial xr-support. Running the tests is not sufficient to know if this is actually working. - <Canvas/> configuration/props: - Shadow-prop: default shadow map - Flat- and linear-prop: tone-mapping and color-management - Frameloop-prop: "always" | "never" | "demand" we expose a render and requestRender-function from useThree() Other changes: - Use tsup instead of vite for building - Cleanup vite.config.ts - Bump version number to 0.3.0
In comparison with
I created testing utilities for
From userland there are currently little changes, now that I re-implemented most of the API, except from some internals
Yes, I agree. I (and chatgpt) provided jsdoc comments for most of the functions, also internal ones. But we need documentation/examples, for sure. A REPL would be very handy. |
- add chatgpt docs
LinearEncoding and sRGBEncoding is not included anymore in later versions of threejs. react-three-fiber hardcoded these enums. see pmndrs/react-three-fiber#2829
- remove `@types/three` and `zustand` from dependencies - add `@types/three` to peer-dependencies - update `three`, `tsup` and `solid-js`in dev-dependencies update pnpm-lock.yaml
This prevents flashes.
before - createThree and other initialisation code was called immediately after declaring canvas - this caused issues with binding pointer-events on macOS chrome 125.0.6422.78 (arm64) after - createThree and other initialisation code is wrapped in onMount
- add comments - extract type-utilities into ./type-utils.ts - export under the `S3` namespace - (fix) infer THREE.Color correctly - simplify types - remove types from jsdoc comments
before - `solid-three` does not expose api to set the core elements from `useThree`. - In `react-three-fiber` you can set core elements from `useThree` with zustand: you directly set the element in the store and it is the responsibility of the caller to manage proper cleanup. - an example of how this clean-up looks like: createEffect(() => { const oldCam = untrack(() => store.camera) store.set({ camera }) onCleanup(() => { store.set({ camera: oldCam }) }) }) - this is bug-prone since it relies on there only being a single camera that overwrites the default camera. When there are multiple cameras, the order of unmounting could create unwanted side-effects. after - use stack-like data-structure to manage all the core-elements: `Stack` and `AugmentedStack`. - the top element is being used as element in the store with `stack.peek()`. - push returns a cleanup-function - pushed element is automatically removed onCleanup - a warning is given in dev-mode if - There are more then 2 elements in the stack (the default and an overriding element), since this still could lead to unexpected behavior. - An element is added to the stack outside of a `createRoot` or `render`, since this will require manual cleanup. - TODO: improve warning messages. also - adjusted implementation `withMultipleContext`. - return-type `withContext<T>()` and `withMultipleContext<T>()` is `T` instead of `Accessor<T>`. - wheel-event is passive in `createEvents`. remove packageManager-property from package.json
Following api still needs to be implemented:
Following api might be implemented (let's discuss)
|
Implementation of proxy-based threejs renderer, based on the exploration done in the zustand-to-store branch.
This branch deviates from the previous goal of staying close to r3f's codebase in favor of simplification and
solidification
Similarities
Differences
$S3C
symbol)useThree
returns canvas, threejs' webgl-renderer, camera, raycaster and scene.useLoader
is a very minimal wrapper aroundcreateResource
.{}
.extend(THREE)
if you do not want to think about treeshaking.